﻿
//#define USBASP_FUNC_CONNECT     1 	连接到设备
//#define USBASP_FUNC_DISCONNECT  2 	释放连接
//#define USBASP_FUNC_TRANSMIT    3 	传输
//#define USBASP_FUNC_READFLASH   4 	读FLASH
//#define USBASP_FUNC_ENABLEPROG  5 	允许编程
//#define USBASP_FUNC_WRITEFLASH  6 	写FLASH
//#define USBASP_FUNC_READEEPROM  7 	读EEPROM
//#define USBASP_FUNC_WRITEEEPROM 8 	写EEPROM
//#define USBASP_FUNC_SETLONGADDRESS 9	设置远程地址

//Device Descriptor:
//bcdUSB:             0x0110
//bDeviceClass:         0xFF
//bDeviceSubClass:      0x00
//bDeviceProtocol:      0x00
//bMaxPacketSize0:      0x08 (8)
//idVendor:           0x16C0
//idProduct:          0x05DC
//bcdDevice:          0x0102
//iManufacturer:        0x01
//iProduct:             0x02
//iSerialNumber:        0x00
//bNumConfigurations:   0x01

//ConnectionStatus: DeviceConnected
//Current Config Value: 0x00
//Device Bus Speed:      Low
//Device Address:       0x02
//Open Pipes:              0

//发出ChipErase指令后等待足够的时间，对于S5x应至少等待500ms，对于AVR应至少等待9ms

using System;
using System.Text;
using System.Windows.Forms;
using n_Config;
using n_CPUType;

using LibUsbDotNet.Usb;
using LibUsbDotNet.Usb.Main;

namespace n_ISP
{
	//****************************************************************
	//格式转换类
	public static class CodeSwitch
	{
		//把机器码文件格式转换成内存代码格式, 用十六进制文本表示
		public static string SetCodeText( string Code )
		{
			Code = Code.TrimEnd( "\n\t ".ToCharArray() );
			string[] Lines = Code.Split( '\n' );
			
			StringBuilder TextBuffer = new StringBuilder( "" );
			string TextChar = null;
			
			int CAddress = 0;	//当前地址
			
			for( int i = 0; i < Lines.Length; ++i ) {
				//判断格式是否正确
				if( !Lines[ i ].StartsWith( ":" ) ) {
					MessageBox.Show( "HEX文件格式错误, 每条记录应该以字符':'开始" );
					return null;
				}
				string SLine = Lines[ i ];
				if( SLine.Length % 2 != 1 || SLine.Length < 11 ) {
					MessageBox.Show( "HEX文件格式错误, 当前记录的长度无效" );
					return null;
				}
				//读取当前记录的各个字段
				string DataLength = SLine.Substring( 1, 2 );
				string Address = SLine.Substring( 3, 4 );
				string Type = SLine.Substring( 7, 2 );
				string Data = SLine.Substring( 9, SLine.Length - 11 );
				string CheckSum = SLine.Substring( SLine.Length - 2, 2 );
				
				//判断记录长度是否合法
				int IdataLength = int.Parse( DataLength, System.Globalization.NumberStyles.HexNumber );
				if( IdataLength * 2 != Data.Length ) {
					MessageBox.Show( "HEX文件格式错误, 当前记录的长度无效: " + IdataLength + " " + DataLength );
					return null;
				}
				//判断校验和
				int IcheckSum = 0;
				for( int j = 1; j < SLine.Length; j += 2 ) {
					IcheckSum += int.Parse( SLine[ j ].ToString() + SLine[ j + 1 ], System.Globalization.NumberStyles.HexNumber );
					IcheckSum %= 256;
				}
				if( IcheckSum != 0 ) {
					MessageBox.Show( "HEX文件格式错误, 校验和出错: " + SLine );
					return null;
				}
				//判断是否结束记录
				if( Type == "01" ) {
					if( i != Lines.Length - 1 ) {
						MessageBox.Show( "HEX文件格式错误, 结束记录标志之后不能有记录" );
						return null;
					}
					break;
				}
				//忽略其他类型记录
				if( Type != "00" ) {
					continue;
				}
				//填充默认数据
				int IAddress = int.Parse( Address, System.Globalization.NumberStyles.HexNumber );
				while( CAddress < IAddress ) {
					TextChar += '.';
					TextBuffer.Append( " FF" );
					++CAddress;
					if( CAddress % 16 == 0 ) {
						TextBuffer.Append( "    " );
						TextBuffer.Append( TextChar );
						TextBuffer.Append( "\n" );
						TextChar = null;
					}
				}
				//填充实际数据
				int Index = 0;
				while( CAddress < IAddress + Data.Length / 2 ) {
					TextBuffer.Append( " " + Data[ Index ] + Data[ Index + 1 ] );
					int Value = int.Parse( Data[ Index ].ToString() + Data[ Index + 1 ], System.Globalization.NumberStyles.HexNumber );
					if( Value >= 32 && Value <= 126 ) {
						TextChar += (char)Value;
					}
					else {
						TextChar += '.';
					}
					Index += 2;
					++CAddress;
					if( CAddress % 16 == 0 ) {
						TextBuffer.Append( "    " );
						TextBuffer.Append( TextChar );
						TextBuffer.Append( "\n" );
						TextChar = null;
					}
				}
			}
			return TextBuffer.ToString();
		}
		
		//把内存代码格式分割成256字节分组的数据列表
		public static string[] SwitchTextToArray( string Code )
		{
			StringBuilder Result = new StringBuilder( null );
			int Address = 0;
			string[] Codes = Code.Split( '\n' );
			int CodesLength = Codes.Length;
			
			for( int Line = 0; Line < CodesLength; ++Line ) {
				int CurentLineLength = Codes[ Line ].Length;
				for( int i = 0; i < 3 * 16; i += 3 ) {
					if( i + 2 >= CurentLineLength ) {
						break;
					}
					string HEXstring = Codes[ Line ][ i + 1 ].ToString() + Codes[ Line ][ i + 2 ];
					int D = int.Parse( HEXstring, System.Globalization.NumberStyles.HexNumber );
					Result.Append( D + " " );
					++Address;
					if( Address % 128 == 0 ) {
						Result.Append( "\n" );
					}
				}
			}
			string[] cut = Result.ToString().TrimEnd( '\n' ).Split( '\n' );
			for( int i = 0; i < cut.Length; ++i ) {
				cut[ i ] = cut[ i ].TrimEnd( ' ' );
			}
			return cut;
		}
	}
	//****************************************************************
	//芯片下载类
	public static class ISP
	{
		public delegate void deleProgressStep( int Max, int Current );
		public static deleProgressStep ProgressStep;
		
		public delegate void deleISPStep( string Mes );
		public static deleISPStep ISPStep;
		
		static ProgressBar ProgBar;
		
		//初始化
		public static void Init()
		{
			//芯片集初始化
			ChipList.Init();
			
			ProgBar = new ProgressBar();
		}
		
		//设置进度条
		public static void SetProgress( ProgressBar p )
		{
			ProgBar = p;
		}
		
		//自动操作
		public static void DownLoad( string Code )
		{
			try {
			
			//设置芯片
			if( Config.ChipNumber == 0 ) {
				//Config.AddCPU( 0, CPUType.DefaultChip );
				MessageBox.Show( "没有设置目标芯片" );
				return;
			}
			ChipList.SetChip( Config.GetCPU() );
			
			//开始USB通信
			if( ISPStep != null ) {
				ISPStep( "开始USB通信" );
			}
			string m = USB.StartDevice();
			if( m != null ) {
				MessageBox.Show( m, "下载失败" );
				if( ISPStep != null ) {
					ISPStep( m );
				}
				return;
			}
			//比较芯片ID是否一致
			if( ISPStep != null ) {
				ISPStep( "比较芯片ID..." );
			}
			Chip chip = ChipList.GetSelectedChip();
			byte[] ID = null;
			int ErrorTime = 0;
			int MaxTime = 4;
			do {
				if( ErrorTime > 0 ) {
					USB.CloseDevice();
					System.Threading.Thread.Sleep( 300 );
					string mm = USB.StartDevice();
					System.Threading.Thread.Sleep( 300 );
				}
				try {
					ID = ISP.ReadChipID();
				}
				catch {
					MessageBox.Show( "读取ID异常,请重新插入下载线" );
					USB.CloseDevice();
					return;
				}
				++ErrorTime;
				if( ErrorTime > MaxTime ) {
					MessageBox.Show( "当前芯片和目标板芯片ID不同: " + ID[ 0 ] + "," + ID[ 0 ] + "," + ID[ 0 ] + " - " + chip.ChipID1 + "," + chip.ChipID2 + "," + chip.ChipID3 );
					USB.CloseDevice();
					return;
				}
			}
			while( ID[ 0 ] != chip.ChipID1 || ID[ 1 ] != chip.ChipID2 || ID[ 2 ] != chip.ChipID3 );
			
			//擦除芯片
			if( ISPStep != null ) {
				ISPStep( "擦除芯片..." );
			}
			ISP.Erase();
			
			//写入Flash
			if( ISPStep != null ) {
				ISPStep( "下载程序..." );
			}
			ISP.WriteFlash( CodeSwitch.SetCodeText( Code ) );
			
			//关闭USB设备
			USB.CloseDevice();
			if( ISPStep != null ) {
				ISPStep( "自动操作完成" );
			}
			}catch(Exception e) {
				MessageBox.Show( "程序下载异常: " + e.ToString() );
			}
		}
		
		//擦除芯片
		public static void Erase()
		{
			byte[] p = new byte[4];
			USB.Send( 0xc0, 0x03, 0x80ac, 0, p );
			//芯片擦除时应等待500ms
			System.Threading.Thread.Sleep( 500 );
		}
		
		//检查空片
		public static bool CheckEmpty()
		{
			byte[] command = new byte[4];
			byte[] Buffer = new byte[128];
			int Waste = 0;
			int Number = ChipList.GetSelectedChip().FlashSize;
			ProgBar.Maximum = Number;
			for( int Address = 0; Address < Number; Address += 128 ) {
				
				System.Windows.Forms.Application.DoEvents();
				
				//设置默认数据
				SetDefalseData( Buffer );
				//设置远程地址
				USB.Send( 0xc0, 0x09, Address, 0, command );
				System.Threading.Thread.Sleep( 10 );
				//读flash
				USB.Send( 0xc0, 0x04, Address, 0, Buffer );
				System.Threading.Thread.Sleep( 10 );
				
				//如果读取失败,重新读取
				if( DataIsDefault( Buffer ) ) {
					Address -= 128;
					++Waste;
					continue;
				}
				//判断数据是否为0xff
				for( int i = 0; i < 128; ++i ) {
					if( Buffer[ i ] != 0xff ) {
						ProgBar.Value = 0;
						return false;
					}
				}
				ProgBar.Value = Address;
			}
			ProgBar.Value = 0;
			return true;
		}
		
		//写入Flash
		public static void WriteFlash( string Code )
		{
			string[] HEX = CodeSwitch.SwitchTextToArray( Code );
			int Address = 0;
			int Number = HEX.Length;
			ProgBar.Maximum = Number;
			for(int i = 0; i < HEX.Length; ++i ) {
				
				System.Windows.Forms.Application.DoEvents();
				
				string[] Cut = HEX[ i ].Split( ' ' );
				byte[] p = new byte[ Cut.Length ];
				for( int j = 0; j < Cut.Length; ++j ) {
					p[ j ] = (byte)int.Parse( Cut[ j ] );
				}
				int StartEnfFlag = 0;
				//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
				//请注意以下这里,用0x80不能下载MEGA8,用0x40可以;而且0x40也可以下载MEGA32(没有测试89S52)
				
				//用这段的话下载之后 MEGA8 运行不对, S52下载不了
//				if( i == 0 ) {
//					StartEnfFlag = 0x0180;  //开始
//				}
//				else if( i == HEX.Length - 1 ) {
//					StartEnfFlag = 0x0280;  //结束
//				}
//				else {
//					StartEnfFlag = 0x0080;  //中间
//				}
				//用这段可以下载 MEGA8 和 MEGA32, S52 下载不了
				if( i == 0 ) {
					StartEnfFlag = 0x0140;  //开始
				}
				else if( i == HEX.Length - 1 ) {
					StartEnfFlag = 0x0240;  //结束
				}
				else {
					StartEnfFlag = 0x0040;  //中间
				}
				//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
				
				//写入flash
				USB.Send( 0xc0, 0x09, Address, 0, p );
				USB.Send( 0x40, 0x06, Address, StartEnfFlag, p );
				Address += 128;
				ProgBar.Value = i;
				if( ProgressStep != null ) {
					ProgressStep( Number, i );
				}
			}
			ProgBar.Value = 0;
		}
		
		//校验Flash
		public static bool CheckFlash( string Code )
		{
			string[] HEX = CodeSwitch.SwitchTextToArray( Code );
			ProgBar.Maximum = HEX.Length;
			byte[] command = new byte[4];
			byte[] Buffer = new byte[128];
			
			for(int i = 0, Address = 0; i < HEX.Length; ++i, Address += 128 ) {
				
				System.Windows.Forms.Application.DoEvents();
				
				string[] Cut = HEX[ i ].Split( ' ' );
				byte[] p = new byte[ Cut.Length ];
				for( int j = 0; j < Cut.Length; ++j ) {
					p[ j ] = (byte)int.Parse( Cut[ j ] );
				}
				//设置默认数据
				SetDefalseData( Buffer );
				//设置远程地址
				USB.Send( 0xc0, 0x09, Address, 0, command );
				System.Threading.Thread.Sleep( 10 );
				//读flash
				USB.Send( 0xc0, 0x04, Address, 0, Buffer );
				System.Threading.Thread.Sleep( 10 );
				
				//如果读取失败,重新读取
				if( DataIsDefault( Buffer ) ) {
					Address -= 128;
					--i;
					continue;
				}
				//判断数据是否一致
				for( int n = 0; n < p.Length; ++n ) {
					if( Buffer[ n ] != p[ n ] ) {
						ProgBar.Value = 0;
						return false;
					}
				}
				++ProgBar.Value;
				System.Threading.Thread.Sleep( 2000 );
			}
			ProgBar.Value = 0;
			return true;
		}
		
		//读取Flash
		public static void ReadFlash()
		{
			//CodeBox.Clear();
			byte[] command = new byte[4];
			byte[] Buffer = new byte[128];
			int Waste = 0;
			int Number = ChipList.GetSelectedChip().FlashSize;
			ProgBar.Maximum = Number;
			for( int Address = 0; Address < Number; Address += 128 ) {
				
				System.Windows.Forms.Application.DoEvents();
				
				//设置默认数据
				SetDefalseData( Buffer );
				//设置远程地址
				USB.Send( 0xc0, 0x09, Address, 0, command );
				System.Threading.Thread.Sleep( 10 );
				//读flash
				USB.Send( 0xc0, 0x04, Address, 0, Buffer );
				System.Threading.Thread.Sleep( 10 );
				
				//如果读取失败,重新读取
				if( DataIsDefault( Buffer ) ) {
					Address -= 128;
					++Waste;
					continue;
				}
				//添加文本
				//CodeBox.Add( Buffer );
				ProgBar.Value = Address;
			}
			System.Threading.Thread.Sleep( 500 );
			//显示文本
			//CodeBox.ShowBuffer();
			ProgBar.Value = 0;
		}

		//读取芯片标志位
		public static byte[] ReadChipID()
		{
			byte[] ID = new byte[ 3 ];
			byte[] pp = new byte[ 4 ];
			
			//读取芯片标识字
			for( int i = 0; i < 3; ++i ) {
				USB.Send( 0xc0, 0x03, 0x30, i, pp ); //读取标识字节
				ID[ i ] = pp[ 3 ];
			}
			return ID;
		}
		
		//读取熔丝
		public static byte[] ReadFuse()
		{
			byte[] Fuse = new byte[ 3 ];
			byte[] pp = new byte[ 4 ];
			
			//读取熔丝低位
			USB.Send( 0xc0, 0x03, 0x0050, 0x00, pp );
			Fuse[ 0 ] = pp[ 3 ];
			
			//读取熔丝高位
			USB.Send( 0xc0, 0x03, 0x0858, 0x00, pp );
			Fuse[ 1 ] = pp[ 3 ];
			
			//读取熔丝扩展位
			USB.Send( 0xc0, 0x03, 0x0850, 0x00, pp );
			Fuse[ 2 ] = pp[ 3 ];
			
			return Fuse;
		}
		
		//设置熔丝
		public static void WriteFuse( byte Low, byte High )
		{
			byte[] pp = new byte[ 4 ];
			
			//写入熔丝低位
			USB.Send( 0xc0, 0x03, 0xA0AC, Low * 256 + 0x00, pp );
			
			//写入熔丝高位
			USB.Send( 0xc0, 0x03, 0xA8AC, High * 256 + 0x00, pp );
			
			//写入熔丝扩展位
			//USB.Send( 0xc0, 0x03, 0xA4AC, Ext * 256 + 0x00, pp );
			
			//--------------------------------------------
			//以下程序是猜测的
			//注意不行!!! 锁住了
			//写入熔丝低位
			//pp[ 3 ] = Low;
			//USB.Send( 0xc0, 0x03, 0xA0AC, 0x00, pp );
			
			//写入熔丝高位
			//pp[ 3 ] = High;
			//USB.Send( 0xc0, 0x03, 0xA8AC, 0x00, pp );
			
			//写入熔丝扩展位
			//pp[ 3 ] = Ext;
			//USB.Send( 0xc0, 0x03, 0xA4AC, 0x00, pp );
		}
		
		//读取锁定位
		public static byte ReadLock()
		{
			byte[] pp = new byte[ 4 ];
			
			//读取锁定位
			USB.Send( 0xc0, 0x03,0x58, 0x00, pp );
			return pp[ 3 ];
		}
		
		//读取时钟校正值
		public static byte[] ReadClockBration()
		{
			byte[] Clock = new byte[ 4 ];
			byte[] pp = new byte[ 4 ];
			
			//读取时钟校验值
			USB.Send( 0xc0, 0x03,0x38, 0x00, pp );//读取时钟校验值1
			Clock[ 0 ] = pp[ 3 ];
			USB.Send( 0xc0, 0x03,0x38, 0x01, pp );//读取时钟校验值2
			Clock[ 1 ] = pp[ 3 ];
			USB.Send( 0xc0, 0x03,0x38, 0x02, pp );//读取时钟校验值3
			Clock[ 2 ] = pp[ 3 ];
			USB.Send( 0xc0, 0x03,0x38, 0x03, pp );//读取时钟校验值4
			Clock[ 3 ] = pp[ 3 ];
			
			return Clock;
		}
		
		//设置默认数据
		static void SetDefalseData( byte[] Buffer )
		{
			for( int i = 0; i < Buffer.Length; ++i ) {
				Buffer[ i ] = (byte)( i + 64 );
			}
		}
		
		//判断数据是否为默认的数据
		static bool DataIsDefault( byte[] Buffer )
		{
			for( int i = 0; i < Buffer.Length; ++i ) {
				if( Buffer[ i ] != i + 64 ) {
					return false;
				}
			}
			return true;
		}
	}
	//****************************************************************
	//USB设备
	public static class USB
	{
		//2013年10月15日
		//描述: 经过修改,下边的ID可以用于Win7,而且很稳定
		
		//描述：这是最先采用的驱动，不过只支持WinXP
		//2013.7.22(采用)文件夹的驱动
		const int VID_DEF = 0x16C0;
		const int PID_DEF = 0x05DC;
		
		//免驱动USB设备
		const int VID = 0x03EB;
		const int PID = 0xC8B4;
		
		//描述：这是目前采用的，支持WinXP和Win7
		//驱动文件序号: 2013.1.29
		//const int VID = 0x03eb;
		//const int PID = 0xc7b4;
		
		static UsbDevice dev;
		
		//开始USB通信(最新版)
		//2013.10.13 0:22 修改,主要是增加了延时,效果有些改善
		public static string StartDevice()
		{
			byte[] p = new byte[4];
			
			//检测USBASP硬件(先检测新版下载线, 检测不到的话再检测老版的下载线)
			if ( !OpenDevice( VID_DEF, PID_DEF ) ) {
				System.Threading.Thread.Sleep( 20 );
				if( !OpenDevice( VID, PID ) ) {
					return "请把下载线连到电脑USB端口上，如果问题依旧，请重新插拔下载线或重启本软件。";
				}
			}
			System.Threading.Thread.Sleep( 20 );
			
			//连接到设备
			for( int i = 0; i < 30; ++i ) {
				if( ConnectDeviceOK() ) {
					return null;
				}
			}
			USB.CloseDevice();
			return "请把下载线插到主控制小板上, 如果问题依旧，请重新插拔下载线或重启本软件。";
		}
		
		//发送信息
		public static void Send( int RequestType, int Request, int Value, int Index, byte[] buffer )
		{
			dev.IOControlMessage( RequestType, Request, Value, Index, buffer, 1000 );
		}
		
		//关闭设备
		public static void CloseDevice()
		{
			if ( dev != null ) {
				Send( 0xC0, 0x02, 0x00, 0x00, new byte[0] );
				//dev.ReleaseInterface( 0 );  //这个语句导致异常
				dev.SetConfiguration( 0 );
				dev.Close();
				dev = null;
			}
		}
		
		// 测试设备是否存在
		public static bool DeviceIsExist()
		{
			try {
			UsbDeviceList devlist = UsbGlobals.DeviceList;
			foreach( UsbDevice Dev in devlist ) {
				if( ( Dev.Info.IdVendor == VID_DEF ) && ( Dev.Info.IdProduct == PID_DEF ) ) {
					return true;
				}
			}
			return false;
			}
			catch {
				return false;
			}
		}
		
		//打开设备
		static bool OpenDevice(int vid, int pid)
		{
			UsbDeviceList devlist = UsbGlobals.DeviceList;
			foreach( UsbDevice Dev in devlist ) {
				if( ( Dev.Info.IdVendor == vid ) && ( Dev.Info.IdProduct == pid ) ) {
					if( Dev.Open() ) {//&& dev.SetConfiguration( 1 ) >= 0 && dev.ClaimInterface( 0 ) >= 0 ) {
						dev = Dev;
						return true;
					}
				}
				else {
					return false;
				}
			}
			return false;
		}
		
		//连接到设备
		static bool ConnectDeviceOK()
		{
			byte[] p = new byte[4];
			
			//连接到设备
			Send( 0xC0, 0x01, 0x06, 0x00, p );
			System.Threading.Thread.Sleep( 20 );
			//测试是否允许编程
			Send( 0xC0, 0x05, 0x00, 0x00, p );
			System.Threading.Thread.Sleep( 20 );
			if( p[0] == 0 ) {
				return true;
			}
			else {
				return false;
			}
		}
	}
	
	//****************************************************************
	//芯片集信息
	public static class ChipList
	{
		static Chip[] ChipSet;
		static int SelectedChipIndex;
		
		//初始化
		public static void Init()
		{
			ChipSet = new Chip[ 9 ];
			ChipSet[ 0 ] = new Chip( "AT89S51", 4096, 0x1E, 0x51, 0x06 );
			ChipSet[ 1 ] = new Chip( "AT89S52", 8192, 0x1E, 0xFF, 0x1E );
			ChipSet[ 2 ] = new Chip( "MEGA48", 1024, 0x1E, 0x92, 0x0A );
			ChipSet[ 2 ] = new Chip( "MEGA328", 32768, 0x1E, 0x95, 0x0F );
			ChipSet[ 3 ] = new Chip( "MEGA8", 8192, 0x1E, 0x93, 0x07 );
			ChipSet[ 4 ] = new Chip( "MEGA16", 16384, 0x1E, 0x94, 0x03 );
			ChipSet[ 5 ] = new Chip( "MEGA32", 32768, 0x1E, 0x95, 0x02 );
			ChipSet[ 6 ] = new Chip( "MEGA64", 32768, 0x1E, 0x96, 0x02 );
			ChipSet[ 7 ] = new Chip( "MEGA128", 32768, 0x1E, 0x97, 0x02 );
			ChipSet[ 8 ] = new Chip( "MEGA644", 65536, 0x1E, 0x96, 0x0A );
			
			SelectedChipIndex = 0;
		}
		
		//设置当前芯片
		public static void SetChip( string Name )
		{
			for( int i = 0; i < ChipSet.Length; ++i ) {
				if( ChipSet[ i ].Name == Name ) {
					SelectedChipIndex = i;
					return;
				}
			}
			MessageBox.Show( "错啦, 未知的芯片: " + Name );
		}
		
		//获取当前选定的芯片
		public static Chip GetSelectedChip()
		{
			return ChipSet[ SelectedChipIndex ];
		}
	}
	//芯片类
	public class Chip
	{
		//构造函数
		public Chip( string vName, int vFlashSize, int vChipID1, int vChipID2, int vChipID3 )
		{
			Name = vName;
			FlashSize = vFlashSize;
			ChipID1 = vChipID1;
			ChipID2 = vChipID2;
			ChipID3 = vChipID3;
		}
		
		public string Name;
		public int FlashSize;
		public int ChipID1;
		public int ChipID2;
		public int ChipID3;
	}
}


//		//开始USB通信
//		static string StartDevice1()
//		{
//			byte[] p = new byte[4];
//			
//			//检测USBASP硬件(先检测新版下载线, 检测不到的话再检测老版的下载线)
//			if ( !OpenDevice( VID, PID ) ) {
//				if( !OpenDevice( VID_XP, PID_XP ) ) {
//					return "请把下载线连到电脑USB端口上，如果问题依旧 请重新插拔下载线或重启本软件等.";
//				}
//			}
//			//连接到设备
//			Send( 0xC0, 0x01, 0x07, 0x00, p );
//			//测试是否允许编程
//			Send( 0xC0, 0x05, 0x00, 0x00, p );
//			if( p[0] == 0 ) {
//				return null;
//			}
//			//连接到设备
//			Send( 0xC0, 0x01, 0x06, 0x00, p );
//			//测试是否允许编程
//			Send( 0xC0, 0x05, 0x00, 0x00, p );
//			if( p[0] == 0 ) {
//				return null;
//			}
//			//USB.CloseDevice();
//			//return "请把下载线插到主控制小板上, 如果问题依旧 请重新插拔下载线或重启本软件等.";
//			return null;
//		}
//		
//		//打开USB设备(非编程模式),用于普通数据通信
//		static string StartDeviceForData()
//		{
//			//检测USBASP硬件(先检测新版下载线, 检测不到的话再检测老版的下载线)
//			if ( !OpenDevice( VID, PID ) ) {
//				if( !OpenDevice( VID_XP, PID_XP ) ) {
//					return "请把下载线连到电脑USB端口上，如果问题依旧 请重新插拔下载线或重启本软件等.";
//				}
//			}
//			return null;
//		}
//		
//		//开始USB通信(改进)
//		static string StartDevice_V1()
//		{
//			byte[] p = new byte[4];
//			
//			//检测USBASP硬件
//			bool isOK = false;
//			for( int i = 0; i < 3; ++i ) {
//				if ( OpenDevice( VID, PID ) ) {
//					isOK = true;
//					break;
//				}
//				System.Threading.Thread.Sleep( 100 );
//			}
//			if( !isOK ) {
//				return "请把下载线连到电脑USB端口上，如果问题依旧 请重新插拔下载线/重启本软件等.";
//			}
//			System.Threading.Thread.Sleep( 100 );
//			
//			//连接到设备
//			Send( 0xC0, 0x01, 0x07, 0x00, p );
//			
//			System.Threading.Thread.Sleep( 50 );
//			
//			//测试是否允许编程
//			Send( 0xC0, 0x05, 0x00, 0x00, p );
//			if( p[0] != 0 ) {
//				//连接到设备
//				Send( 0xC0, 0x01, 0x06, 0x00, p );
//				
//				System.Threading.Thread.Sleep( 100 );
//				
//				//测试是否允许编程
//				Send( 0xC0, 0x05, 0x00, 0x00, p );
//				if( p[0] != 0 ) {
//					USB.CloseDevice();
//					return "请把下载线插到主控制小板上, 如果问题依旧 请重新插拔下载线/重启本软件等.";
//				}
//				return null;
//			}
//			return null;
//		}
//		
//		//开始USB通信(这个是旧版程序)
//		static string StartDeviceOLD()
//		{
//			int TryTime = 0;
//			
//			Start:
//			TryTime += 1;
//			
//			//检测USBASP硬件
//			bool isOK = false;
//			for( int i = 0; i < 3; ++i ) {
//				if ( OpenDevice( VID, PID ) ) {
//					isOK = true;
//					break;
//				}
//				System.Threading.Thread.Sleep( 300 );
//			}
//			if( !isOK ) {
//				return "请把下载线连到电脑USB端口上，或者重新插拔下载线.";
//			}
//			System.Threading.Thread.Sleep( 100 );
//			//连接到设备
//			Send( 0xC0, 0x01, 0, 0, new byte[0] );
//			
//			//测试是否允许编程
//			byte[] p = new byte[1];
//			Send( 0xC0, 0x05, 0, 0, p );
//			if( p[0] != 0 ) {
//				USB.CloseDevice();
//				if( TryTime < 5 ) {
//					goto Start;
//				}
//				return "请把下载线插到主控制小板上, 或者重新插拔下载线.";
//			}
//			return null;
//		}
